package com.guodi.model.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.guodi.common.constant.StatusCode;
import com.guodi.common.utils.AjaxResult;
import com.guodi.common.utils.PageData;
import com.guodi.common.utils.UuidUtil;
import com.guodi.core.boot.ctrl.BaseController;
import com.guodi.core.secure.utils.AuthUtil;
import com.guodi.model.entity.*;
import com.guodi.model.service.*;
import com.guodi.model.utils.ExcelUtil;
import com.guodi.model.utils.RegularUtils;
import com.guodi.model.utils.TimeUtils;
import com.guodi.system.feign.ISysClient;
import com.guodi.system.feign.IUserClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import javax.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @描述：上报值填报表控制类
 * @作者: 代鹏刚
 * @日期: 2020-11-07
 */
@RestController
@RequestMapping("/IdtReportFill")
@Api(value = "API - IdtReportFillController", description = "上报值填报表")
public class IdtReportFillController extends BaseController {

    @Resource
    public IIdtReportFillService idtReportFillService;

    @Resource
    private IIdtReportValueService iIdtReportValueService;

    @Resource
    private IIdtIndicatorsService iIdtIndicatorsService;

    @Resource
    private IIdtReportFileService iIdtReportFileService;

    @Resource
    private IIdtIndicatorsTypeService iIdtIndicatorsTypeService;

    @Resource
    private IIdtIndicatorsDirService iIdtIndicatorsDirService;

    @Resource
    private IIdtMonitorValueService iIdtMonitorValueService;

    @Resource
    IUserClient iUserClient;

    @Resource
    private ISysClient iSysClient;

    /**
    * @描述: 根据实体属性查询
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020-11-07
    **/
    @PostMapping("/listByEntity")
    @ApiOperation(value = " 根据实体属性查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "indicatorsId", value = "指标ID", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "userDivision", value = "行政区划代码(多个使用逗号隔开)", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult listByEntity(String indicatorsId, String userDivision){
        //存储指标集合
        List<String> ids = new ArrayList<>();
        IdtIndicators idtIndicators = iIdtIndicatorsService.getById(indicatorsId);
        if(StringUtils.isNotBlank(idtIndicators.getDatasource()) && idtIndicators.getDatasource().equals("formula")){
            if(StringUtils.isNotBlank(idtIndicators.getCalculateResult())){
                List<String> codes = RegularUtils.extractString(idtIndicators.getCalculateResult());
                ids = iIdtIndicatorsService.listEntityByCode(codes);
                ids.add(indicatorsId);
            }else {
                return new AjaxResult(StatusCode.ERROR_CODE_40005,"该复合指标请先配置计算公式");
            }
        }else {
            ids.add(indicatorsId);
        }
        List<IdtReportFill> idtReportFills = idtReportFillService.listByData(ids, userDivision.split(","));
        //获取行政区划
        PageData pageData = new PageData();
        List<PageData> divisionList = iIdtIndicatorsService.listDivisionByEntity(pageData);
        Map<String, String> dictMap = new HashMap<>();
        for (PageData data : divisionList) {
            dictMap.put(data.get("code").toString(), data.get("name").toString());
        }
        idtReportFills = idtReportFills.stream().map(fill -> {
            if (indicatorsId.equals(fill.getIndicatorsId())) {
                fill.setDatasource("formula");
                fill.setSort(9999);
            } else {
                fill.setSort(0);
            }
            fill.setDivisionName(dictMap.get(fill.getDivisionCode()));
            return fill;
        }).collect(Collectors.toList());
        //按指标体系配置顺序排序
        idtReportFills = idtReportFills.stream().sorted(Comparator.comparing(IdtReportFill::getSort)).collect(Collectors.toList());
        Map<Integer, List<IdtReportFill>> resultMap = idtReportFills.stream().collect(Collectors.groupingBy(IdtReportFill::getYear));
        Map<Integer, List<IdtReportFill>> result = new HashMap<>();
        for (Integer key : resultMap.keySet()) {
            List<IdtReportFill> idtReportFillList = resultMap.get(key);
            // 获取当前分类中value的ID集合
            List<String> allIds = idtReportFillList.stream().map(x->x.getIndicatorsId()).collect(Collectors.toList());
            // 获取分类中不存在的指标ID数据集
            List<String> resultIds = ids.stream().filter(x->!allIds.contains(x)).collect(Collectors.toList());
            if(resultIds.size() > 0){
                for (String id:resultIds) {
                    // 缺失指标上报值，则补充
                    IdtReportFill idtReportFill = new IdtReportFill();
                    idtReportFill.setId(UuidUtil.get32UUID());
                    idtReportFill.setYear(idtReportFillList.get(0).getYear());
                    idtReportFill.setDivisionCode(idtReportFillList.get(0).getDivisionCode());
                    idtReportFill.setIndicatorsId(id);
                    idtReportFill.setOrgId(idtReportFillList.get(0).getOrgId());
                    idtReportFillList.add(idtReportFill);
                }
            }
            result.put(key,idtReportFillList);
        }
        // 查询同期的监测值
        for(Map.Entry<Integer, List<IdtReportFill>> entry : resultMap.entrySet()) {
            List<IdtReportFill> reportFills = entry.getValue();
            for(IdtReportFill reportFill : reportFills) {
                LambdaQueryWrapper<IdtMonitorValue> lambdaQueryWrapper = new LambdaQueryWrapper();
                lambdaQueryWrapper.eq(IdtMonitorValue::getIndicatorsId,reportFill.getIndicatorsId());
                lambdaQueryWrapper.eq(IdtMonitorValue::getYear,reportFill.getYear());
                lambdaQueryWrapper.eq(IdtMonitorValue::getDivisionCode,reportFill.getDivisionCode());
                lambdaQueryWrapper.orderByDesc(IdtMonitorValue::getCreateTime);
                List<IdtMonitorValue> list = this.iIdtMonitorValueService.list(lambdaQueryWrapper);
                if (list != null && !list.isEmpty()){
                    reportFill.setMonitorValue(list.get(0).getMonitorValue());
                }
            }
        }
        return new AjaxResult(resultMap);
    }

    /**
     * @描述: 新增
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-11-07
     **/
    @PostMapping("/save")
    @ApiOperation(value = "新增")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "formJson", value = "存放上报值对象的json字符串", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult save(String formJson){
        List<IdtReportFill> idtReportFills = JSONObject.parseArray(formJson, IdtReportFill.class);
        if(null == idtReportFills || idtReportFills.size() == 0){
            return new AjaxResult(StatusCode.ERROR_CODE_40005,"参数格式错误，请检查");
        }
        // 检查数据合法性
        AjaxResult checkDataLegitimate = this.checkDataLegitimate(idtReportFills);
        if (checkDataLegitimate != null){
            return checkDataLegitimate;
        }
        for (IdtReportFill idtReportFill : idtReportFills) {
            if(idtReportFill.getCreateTime() == null){
                prepareData(idtReportFill, true);
            }else {
                prepareData(idtReportFill, false);
            }
            if(idtReportFill.getOrgId() == null){
                idtReportFill.setOrgId(this.getUser().getDeptId());
            }
        }
        idtReportFillService.saveOrUpdateBatch(idtReportFills);
        return new AjaxResult();
    }

    /**
     * @描述: 修改
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-11-07
     **/
    @PostMapping("/update")
    @ApiOperation(value = "修改")
    public AjaxResult update(IdtReportFill idtReportFill) {
        prepareData(idtReportFill, false);
        idtReportFillService.updateById(idtReportFill);
        return new AjaxResult();
    }

    /**
     * @描述: 根据主键删除
     * @入参: id
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020-11-07
     **/
    @PostMapping("/delete")
    @ApiOperation(value = "根据主键删除")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "ID", required = true,
                    dataType = "string", paramType = "query")
    })
    public AjaxResult delete(String id){
        idtReportFillService.removeById(id);
        return new AjaxResult();
    }

    /**
     * @描述: 获取指标上报值历史记录
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020/11/7 12:05
     **/
    @PostMapping("/getHistoryList")
    @ApiOperation(value = "获取指标上报值历史记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "current", value = "当前页码", required = true, dataType = "long", paramType = "query", example = "1"),
            @ApiImplicitParam(name = "size", value = "每页显示数量", required = true, dataType = "long", paramType = "query", example = "10"),
            @ApiImplicitParam(name = "year", value = "年份", required = false, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "divisionCode", value = "行政区划代码(4106)", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "indicatorsId", value = "指标ID", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult getHistoryList(@ApiIgnore Page page, String year, String indicatorsId, String divisionCode){
        // 获取指标数据
        IdtIndicators idtIndicators = iIdtIndicatorsService.getById(indicatorsId);
        Map<String, String> deptMap = iIdtIndicatorsService.getDeptNameMap();
        //处理责任处室多级中文名问题
        if(StringUtils.isNotBlank(idtIndicators.getDutyDepartment())){
            idtIndicators.setDutyDepartment(iIdtIndicatorsService.getDeptNameStr(idtIndicators.getDutyDepartment(), deptMap));
        }
        if(StringUtils.isNotBlank(idtIndicators.getDutyCompany())){
            idtIndicators.setDutyCompany(iIdtIndicatorsService.getDeptNameStr(idtIndicators.getDutyCompany(), deptMap));
        }

        //分页获取当前指标下上报值的更新年份记录
        QueryWrapper<IdtReportValue> queryWrapper = new QueryWrapper();
        queryWrapper.select("distinct year");
        queryWrapper.eq("indicators_id",indicatorsId);
        if(StringUtils.isNotBlank(year)){
            queryWrapper.eq("year", Integer.valueOf(year));
        }
        if(StringUtils.isNotBlank(divisionCode)){
            queryWrapper.eq("division_code", divisionCode);
        }
        queryWrapper.orderByDesc("year");
        IPage<IdtReportValue> iPage = iIdtReportValueService.page(page, queryWrapper);
        List<IdtReportValue> list = iPage.getRecords();
        if(list.size() == 0 || list.toString().equals("[null]") || list.toString().equals("null")){
            return new AjaxResult();
        }
        List<Integer> yearList = list.stream().map(x -> x.getYear()).collect(Collectors.toList());
        iPage.setTotal(yearList.size());
        //获取各行政区划的指标上报值
        List<IdtReportValue> idtReportValues = iIdtReportValueService.getHistoryList(indicatorsId,yearList,divisionCode);

        Boolean isFormula = false;
        List<String> idList = new ArrayList<>();
        // 判断是否是复合指标
        if("formula".equals(idtIndicators.getDatasource())){
            if(StringUtils.isBlank(idtIndicators.getCalculateResult())){
                return new AjaxResult(StatusCode.ERROR_CODE_40005,"该复合指标请先配置计算公式");
            }
            isFormula = true;
            QueryWrapper<IdtIndicators> queryWrapper1 = new QueryWrapper();
            List<String> result = RegularUtils.extractString(idtIndicators.getCalculateResult());
            queryWrapper1.in("code",result);
            List<IdtIndicators> indicators = iIdtIndicatorsService.list(queryWrapper1);
            idList = indicators.stream().map(IdtIndicators::getId).collect(Collectors.toList());
        }
        //数据处理，返回指定格式数据
        List<List<Map<String, Object>>> resultList = new ArrayList<>();
        for (Integer yearParam:yearList) {
            List<Map<String, Object>> maps = new ArrayList<>();
            Map<String, Object> map = new HashMap<>();
            map.put("time", yearParam.toString());
            maps.add(map);
            for (IdtReportValue idtReportValue:idtReportValues) {
                if(idtReportValue.getYear().equals(yearParam)){
                    Map<String, Object> m = new HashMap<>();
                    Map<String, Object> value = new HashMap<>();
                    value.put("monitorValue",idtReportValue.getMonitorValue());
                    value.put("reportValue",idtReportValue.getValue());
                    // 如果是复合指标，则查询该指标关联因子数值
                    if(isFormula){
                        Map<String, Object> mObject = new HashMap<>();
                        List<IdtReportValue> reportValues = iIdtReportValueService.listByIndicatorsIds(idList, yearParam, idtReportValue.getDivisionCode());
                        for (IdtReportValue r:reportValues) {
                            mObject.put(r.getIdtName(),r.getValue());
                        }
                        value.put("formulaData",mObject);
                    }
                    m.put(idtReportValue.getDivisionName(), value);
                    //默认只有一条符合条件，便于查看附件
                    m.put("dutyCompany", idtIndicators.getDutyCompany());
                    m.put("dutyDepartment",idtIndicators.getDutyDepartment());
                    try {
                        Long id = Long.valueOf(idtReportValue.getCreator());
                        m.put("creator", iUserClient.userInfoById(id).getData().getUserName());
                    } catch (Exception e) {
                        m.put("creator", idtReportValue.getCreator());
                    }
                    m.put("createTime", idtReportValue.getCreateTime() == null ? null : idtReportValue.getCreateTime());
                    m.put("reportId", idtReportValue.getId());
                    m.put("explain",idtReportValue.getExplain() == null ? null : idtReportValue.getExplain());
                    // 判断是否存在附件
                    LambdaQueryWrapper<IdtReportFile> queryWrapper1 = new QueryWrapper().lambda();
                    queryWrapper1.eq(IdtReportFile::getReportId,idtReportValue.getId());
                    List<IdtReportFile> idtReportFiles = iIdtReportFileService.list(queryWrapper1);
                    if(idtReportFiles.size() > 0){
                        m.put("reportStatus", true);
                    }else {
                        m.put("reportStatus", false);
                    }
                    maps.add(m);
                }
            }
            resultList.add(maps);
        }
        //获取当前指标下所有已存在监测值的行政区划
        List<String> nameList = idtReportValues.stream().sorted(Comparator.comparing(IdtReportValue::getDivisionCode))
                .map(x -> x.getDivisionName()).distinct().collect(Collectors.toList());
        Map result = new HashMap();
        result.put("resultList",resultList);
        result.put("nameList", nameList);
        result.put("iPage",iPage);
        return new AjaxResult(result);
    }


    /**
     * @描述: 指标上报值历史记录导出
     * @入参:
     * @出参:
     * @作者: 代鹏刚
     * @日期: 2020/11/10 11:18
     **/
    @PostMapping("/exportHistoryList")
    @ApiOperation(value = "指标上报值历史记录导出")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "current", value = "当前页码", required = true, dataType = "long", paramType = "query", example = "1"),
            @ApiImplicitParam(name = "size", value = "每页显示数量", required = true, dataType = "long", paramType = "query", example = "10"),
            @ApiImplicitParam(name = "year", value = "年份", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "divisionCode", value = "行政区划代码(4106)", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "indicatorsId", value = "指标ID", required = true, dataType = "string", paramType = "query")
    })
    public void exportHistoryList(@ApiIgnore Page page, String year, String indicatorsId, String divisionCode, HttpServletResponse response){
        // 获取指标数据
        IdtIndicators idtIndicators = iIdtIndicatorsService.getById(indicatorsId);

        Map<String, String> deptMap = iIdtIndicatorsService.getDeptNameMap();
        //处理责任处室多级中文名问题
        if(StringUtils.isNotBlank(idtIndicators.getDutyDepartment())){
            idtIndicators.setDutyDepartment(iIdtIndicatorsService.getDeptNameStr(idtIndicators.getDutyDepartment(), deptMap));
        }
        if(StringUtils.isNotBlank(idtIndicators.getDutyCompany())){
            idtIndicators.setDutyCompany(iIdtIndicatorsService.getDeptNameStr(idtIndicators.getDutyCompany(), deptMap));
        }

        //分页获取当前指标下上报值的更新年份记录
        QueryWrapper<IdtReportValue> queryWrapper = new QueryWrapper();
        queryWrapper.select("distinct year");
        queryWrapper.eq("indicators_id",indicatorsId);
        if(StringUtils.isNotBlank(year)){
            queryWrapper.eq("year", Integer.valueOf(year));
        }
        if(StringUtils.isNotBlank(divisionCode)){
            queryWrapper.eq("division_code", divisionCode);
        }
        queryWrapper.orderByDesc("year");
        IPage<IdtReportValue> iPage = iIdtReportValueService.page(page, queryWrapper);
        List<IdtReportValue> list = iPage.getRecords();
        List<Integer> yearList = list.stream().map(x -> x.getYear()).collect(Collectors.toList());

        //获取各行政区划的指标上报值
        List<IdtReportValue> idtReportValues = iIdtReportValueService.getHistoryList(indicatorsId,yearList,divisionCode);

        //获取当前指标下所有已存在监测值的行政区划
        List<String> divisionNameList = idtReportValues.stream().map(x -> x.getDivisionName()).distinct().collect(Collectors.toList());

        // 判断该指标是否是复合指标，如果是符合指标，需要查询相关计算因子
        List<String> calculateFactorNameList = new LinkedList<>();
        List<String> calculateFactorIdList = new LinkedList<>();
        if("formula".equals(idtIndicators.getDatasource())){
            if(StringUtils.isBlank(idtIndicators.getCalculateResult())){
                calculateFactorNameList.add("该复合指标请先配置计算公式");
            }
            QueryWrapper<IdtIndicators> queryWrapper1 = new QueryWrapper();
            List<String> result = RegularUtils.extractString(idtIndicators.getCalculateResult());
            queryWrapper1.in("code",result);
            List<IdtIndicators> indicators = iIdtIndicatorsService.list(queryWrapper1);
            // 获取计算因子指标名列表
            calculateFactorNameList = indicators.stream().map(IdtIndicators::getName).collect(Collectors.toList());
            // 获取计算因子指标id列表
            calculateFactorIdList = indicators.stream().map(IdtIndicators::getId).collect(Collectors.toList());
        }

        //组装导出Excel数据
        List<Object[]> dataList = new ArrayList<Object[]>();
        // 遍历每个年份
        for (Integer time: yearList) {
            Object[] datas = new Object[1 + (2 + calculateFactorIdList.size() + 3 ) * divisionNameList.size() + 2];
            // 动态数据开始填充的下标，动态数据为检测值、上报值、因子的上报值、上报人、上报时间、说明
            int beginIndex = 0;
            // 日期
            datas[beginIndex++] = time;
            // 遍历每个行政区划
            for (String divisionName : divisionNameList) {
                // 指标监测值 & 指标上报值
                for (IdtReportValue idtReportValue:idtReportValues) {
                    if(idtReportValue.getDivisionName().equals(divisionName) && idtReportValue.getYear().equals(time)){
                        // 指标监测值
                        datas[beginIndex++] = idtReportValue.getMonitorValue();
                        // 指标上报值
                        datas[beginIndex++] = idtReportValue.getValue();
                        // 查询因子值
                        if(!calculateFactorIdList.isEmpty()){
                            List<IdtReportValue> reportValues = iIdtReportValueService.listByIndicatorsIds(calculateFactorIdList, time, idtReportValue.getDivisionCode());
                            for (String calculateFactorId : calculateFactorIdList) {
                                IdtReportValue firstReportValue = reportValues.stream().filter(reportValue -> {
                                    return reportValue.getIndicatorsId().equals(calculateFactorId);
                                }).findFirst().orElse(null);
                                datas[beginIndex++] = firstReportValue == null? "":firstReportValue.getValue();
                            }
                        }
                        try {
                            Long id = Long.valueOf(idtReportValue.getCreator());
                            // 填写人
                            datas[beginIndex++] = iUserClient.userInfoById(id).getData().getUserName();
                        } catch (Exception e) {
                            datas[beginIndex++] = idtReportValue.getCreator();
                        }

                        // 填写时间
                        datas[beginIndex++] = TimeUtils.formatDate(idtReportValue.getCreateTime()) ;
                        // 说明
                        datas[beginIndex++] = idtReportValue.getExplain() ;
                        break;
                    }
                }

            }
            // 责任单位，该单元格左边有：日期、各地区动态值（检测值、上报值、因子的上报值、上报人、上报时间、说明）
            datas[1 + divisionNameList.size() * (2 + calculateFactorIdList.size() + 3) ] = idtIndicators.getDutyCompany() ;
            // 责任处室，该单元格左边有：日期、各地区动态值（检测值、上报值、因子的上报值、上报人、上报时间、说明）、责任单位
            datas[1 + divisionNameList.size() * (2 + calculateFactorIdList.size() + 3 )  + 1 ] = idtIndicators.getDutyDepartment() ;
            dataList.add(datas);
        }
        // 表格标题
        LinkedList<List<String>> titleConfigs = new LinkedList<>();
        titleConfigs.add(Arrays.asList("0","0","0","2","日期"));
        for (int i = 0; i < divisionNameList.size(); i++) {
            // 各个地区动态数据的开始填充下标，左边有：日期、上一地区动态值（检测值、上报值、因子的上报值、上报人、上报时间、说明）
            int beginColIndex = 1 + i * (2 + calculateFactorIdList.size() + 3) ;
            // 地区标题
            titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex),String.valueOf(beginColIndex + 2 + calculateFactorIdList.size() + 3 -1),"0","0",divisionNameList.get(i)));
            // 指标的值标题
            titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex),String.valueOf(beginColIndex + 1),"1","1","指标值"));
            titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex),String.valueOf(beginColIndex),"2","2","监测值"));
            titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex + 1),String.valueOf(beginColIndex + 1),"2","2","上报值"));
            // 计算因子的标题
            if (!calculateFactorIdList.isEmpty()) {
                titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex + 2),String.valueOf(beginColIndex + 2 + calculateFactorIdList.size()-1),"1","1","因子值"));
                for (int i1 = 0; i1 < calculateFactorNameList.size(); i1++) {
                    titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex + 2 + i1),String.valueOf(beginColIndex + 2 + i1),"2","2",calculateFactorNameList.get(i1)));
                }
            }
            // 填写人、左边有：日期、上一地区动态值（检测值、上报值、因子的上报值、上报人、上报时间、说明），上一地区动态值（检测值、上报值、因子的上报值）
            titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex + 2 + calculateFactorIdList.size())
                    ,String.valueOf(beginColIndex + 2 + calculateFactorIdList.size()),"1","2","填写人"));
            // 填写时间、左边有：日期、上一地区动态值（检测值、上报值、因子的上报值、上报人、上报时间、说明），上一地区动态值（检测值、上报值、因子的上报值、上报人）
            titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex + 2 + calculateFactorIdList.size() + 1)
                    ,String.valueOf(beginColIndex + 2 + calculateFactorIdList.size() + 1),"1","2","填写时间"));
            // 说明、左边有：日期、上一地区动态值（检测值、上报值、因子的上报值、上报人、上报时间、说明），上一地区动态值（检测值、上报值、因子的上报值、上报人、填写时间）
            titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex + 2 + calculateFactorIdList.size() + 2)
                    ,String.valueOf(beginColIndex + 2 + calculateFactorIdList.size() + 2),"1","2","说明"));
        }
        // 固定数据开始填充的下标，左边有：日期、各地区动态值（检测值、上报值、因子的上报值、上报人、上报时间、说明）
        int beginColIndex2 = 1 + divisionNameList.size() * (2 + calculateFactorIdList.size() + 3);
        titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex2),String.valueOf(beginColIndex2),"0","2","责任单位"));
        titleConfigs.add(Arrays.asList(String.valueOf(beginColIndex2 + 1),String.valueOf(beginColIndex2 + 1),"0","2","责任处室"));
        response.setHeader("Content-type", "text/html;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        ExcelUtil.exportExcel(response, "评估指标", "评估指标信息", titleConfigs, dataList,3);
    }

    /**
    * @描述: 数据导入验证
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/11/10 17:46
    **/
    @PostMapping("/isExistsReportFill")
    @ApiOperation(value = "数据导入验证")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "code", value = "指标体系编码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "orgId", value = "机构id(65fc1451aa4640c795b971ae9199456c)", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "idtTypeId", value = "指标体系id", required = true, dataType = "string", paramType = "query"),
    })
    public AjaxResult isExistsReportFill(MultipartFile multipartFile, String code, String orgId, String idtTypeId) throws Exception {
        String deptId = this.getUser().getDeptId();
        if (StringUtils.isBlank(deptId)) {
            return new AjaxResult(StatusCode.ERROR_CODE_40005, "该用户所属部门不存在");
        }
        if (multipartFile.isEmpty()) {
            return new AjaxResult(StatusCode.ERROR_CODE_40005, "导入文件不能为空！");
        }
        // 根据上传MultipartFile对象获取excel数据集
        List<List<String>> excelList = ExcelUtil.getExcelData(multipartFile);
        // 预检查
        AjaxResult prepareExcelData = this.prepareExcelData(excelList);
        if (prepareExcelData != null){
            return prepareExcelData;
        }
        // 获取指标体系中的指标数据
        List<String> indicatorsIds = new ArrayList<>();
        IdtIndicatorsType one = this.iIdtIndicatorsTypeService.getById(idtTypeId);
        if(null != one){
            List<ApiIdtIndicatorsDir> treeList = iIdtIndicatorsDirService.listDirByCode(one.getId(), orgId,null);
            indicatorsIds = treeList.stream().filter(x -> x.getType()==2).map(x -> x.getIndicatorsId()).collect(Collectors.toList());
        }
        // 存储新增、更新指标集合
        List<IdtReportFill> repeatingData = new ArrayList<>();
        for (int i = 1; i < excelList.size(); i++) {
            List<String> dataList = excelList.get(i);
            String idtCode = dataList.get(0);
            LambdaQueryWrapper<IdtIndicators> queryWrapper = new QueryWrapper().lambda();
            queryWrapper.eq(IdtIndicators::getCode,idtCode);
            IdtIndicators idtIndicators = iIdtIndicatorsService.getOne(queryWrapper);
            IdtReportFill idtReportFill = new IdtReportFill();
            String year = dataList.get(5).indexOf(".") >=0 ? dataList.get(5).substring(0,dataList.get(5).indexOf(".")) : dataList.get(5);
            idtReportFill.setYear(Integer.parseInt(year));
            if(StringUtils.isNotBlank(dataList.get(4))){
                //可能读成数字了，带小数，去掉小数
                if(dataList.get(4).indexOf(".") != -1){
                    String[] str =  dataList.get(4).split("\\.");
                    idtReportFill.setDivisionCode(str[0]);
                }else{
                    idtReportFill.setDivisionCode(dataList.get(4));
                }
            }
            idtReportFill.setIdtCode(idtCode);
            idtReportFill.setValue(dataList.get(6));
            idtReportFill.setId(UuidUtil.get32UUID());
            idtReportFill.setOrgId(deptId);
            if(idtIndicators != null){
                //判断是否存在相同指标id与行政区划编码与相同年份
                LambdaQueryWrapper<IdtReportFill> queryWrapper1 = new QueryWrapper().lambda();
                queryWrapper1.eq(IdtReportFill::getYear,idtReportFill.getYear());
                queryWrapper1.eq(IdtReportFill::getDivisionCode,idtReportFill.getDivisionCode());
                queryWrapper1.eq(IdtReportFill::getIndicatorsId,idtIndicators.getId());
                List<IdtReportFill> sourceIdtReportValueList = idtReportFillService.list(queryWrapper1);
                if(indicatorsIds.contains(idtIndicators.getId())){
                    if (sourceIdtReportValueList.size() > 0) {
                        repeatingData.add(idtReportFill);
                    }
                }
                // 2021-10-08 陈宏成 取消指标导入时，责任处室的检验判断
//                // 20210701--新增当前用户所属机构与指标的责任处室不一致时，直接给出提示
//                List<Dept> deptList = iSysClient.getDeptChild(Long.valueOf(idtIndicators.getDutyDepartment())).getData();
//                String deptIds = deptList.stream().map(x->x.getId()+"").collect(Collectors.joining(","));
//                if(StringUtils.isNotBlank(deptIds) && deptIds.indexOf(deptId) == -1){
//                    return new AjaxResult(StatusCode.ERROR_CODE_40005, "导入指标的责任处室与当前用户所属处室不一致，请检查填报指标！");
//                }
            }
        }
        String resultCodes = "";
        for (IdtReportFill obj : repeatingData) {
            if (!resultCodes.contains(obj.getIdtCode())) {
                resultCodes += StringUtils.isBlank(resultCodes) ? obj.getIdtCode() : "," + obj.getIdtCode();
            }
        }
        return new AjaxResult(resultCodes);
    }

    /**
    * @描述: 数据导入
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/11/11 9:04
    **/
    @PostMapping("/importExcel")
    @ApiOperation(value = "导入Excel")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "isUpdate", value = "是否覆盖", required = true, dataType = "Boolean", paramType = "query"),
            @ApiImplicitParam(name = "code", value = "指标体系编码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "orgId", value = "机构id(65fc1451aa4640c795b971ae9199456c)", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "idtTypeId", value = "指标体系id", required = true, dataType = "string", paramType = "query"),
    })
    public AjaxResult importExcel(MultipartFile multipartFile, Boolean isUpdate, String code, String orgId, String idtTypeId) {
        List<String> indicatorsIds = new ArrayList<>();
        // 暂时写死
        IdtIndicatorsType one = this.iIdtIndicatorsTypeService.getById(idtTypeId);
        if(null != one){
            List<ApiIdtIndicatorsDir> treeList = iIdtIndicatorsDirService.listDirByCode(one.getId(), null,null);
            indicatorsIds = treeList.stream().filter(x -> x.getType()==2).map(x -> x.getIndicatorsId()).collect(Collectors.toList());
        }
        // 根据上传MultipartFile对象获取excel数据集
        List<List<String>> excelList = ExcelUtil.getExcelData(multipartFile);
        // 预检查
        AjaxResult prepareExcelData = this.prepareExcelData(excelList);
        if (prepareExcelData != null){
            return prepareExcelData;
        }
        // 存储新增、更新指标集合
        List<IdtReportFill> saveUpdateList = new ArrayList<>();
        for (int i = 1; i < excelList.size(); i++) {
            List<String> dataList = excelList.get(i);
            String idtCode = dataList.get(0);
            LambdaQueryWrapper<IdtIndicators> queryWrapper = new QueryWrapper().lambda();
            queryWrapper.eq(IdtIndicators::getCode,idtCode);
            IdtIndicators idtIndicators = iIdtIndicatorsService.getOne(queryWrapper);
            IdtReportFill idtReportFill = new IdtReportFill();
            String year = dataList.get(5).indexOf(".") >=0 ? dataList.get(5).substring(0,dataList.get(5).indexOf(".")) : dataList.get(5);
            idtReportFill.setYear(Integer.parseInt(year));
            if(StringUtils.isNotBlank(dataList.get(4))){
                //可能读成数字了，带小数，去掉小数
                if(dataList.get(4).indexOf(".") != -1){
                    String[] str =  dataList.get(4).split("\\.");
                    idtReportFill.setDivisionCode(str[0]);
                }else{
                    idtReportFill.setDivisionCode(dataList.get(4));
                }
            }
            idtReportFill.setValue(dataList.get(6));
            idtReportFill.setExplain(dataList.get(7));
            idtReportFill.setId(UuidUtil.get32UUID());
            idtReportFill.setOrgId(orgId);
            idtReportFill.setDivisionName(dataList.get(3));
            if(idtIndicators != null){
                //判断是否存在相同指标id与行政区划编码与相同年份
                LambdaQueryWrapper<IdtReportFill> queryWrapper1 = new QueryWrapper().lambda();
                queryWrapper1.eq(IdtReportFill::getYear,idtReportFill.getYear());
                queryWrapper1.eq(IdtReportFill::getDivisionCode,idtReportFill.getDivisionCode());
                queryWrapper1.eq(IdtReportFill::getIndicatorsId,idtIndicators.getId());
                List<IdtReportFill> sourceIdtReportValueList = idtReportFillService.list(queryWrapper1);
                if(sourceIdtReportValueList.size() >0){
                    if(isUpdate != null && isUpdate){
                        IdtReportFill reportValue = sourceIdtReportValueList.get(0);
                        reportValue.setValue(idtReportFill.getValue());
                        reportValue.setExplain(idtReportFill.getExplain());
                        idtReportFill = reportValue;
                    }else{
                        continue;
                    }
                }
                idtReportFill.setIndicatorsId(idtIndicators.getId());
                idtReportFill.setIdtCode(idtIndicators.getCode());
                prepareData(idtReportFill,true);
                if(indicatorsIds.contains(idtIndicators.getId())) {
                    // 过滤掉excel表里面【指标id、行政区划、年份】相同的记录
                    IdtReportFill temp = idtReportFill;
                    saveUpdateList = saveUpdateList.stream().filter(rv -> {
                        return !(Objects.equals(rv.getIndicatorsId(), temp.getIndicatorsId())
                                && Objects.equals(rv.getYear(), temp.getYear())
                                && Objects.equals(rv.getDivisionCode(), temp.getDivisionCode()));
                    }).collect(Collectors.toList());
                    saveUpdateList.add(idtReportFill);
                }
            }
        }
        if(saveUpdateList.size() > 0){
            idtReportFillService.saveOrUpdateBatch(saveUpdateList);
        }
        return new AjaxResult();
    }

    /**
    * @描述: 发布数据验证
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/11/7 14:59
    **/
    @PostMapping("/isExistsReport")
    @ApiOperation(value = "发布数据验证")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "indicatorsId", value = "指标ID（多个使用逗号隔开）", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "userDivision", value = "行政区划编码(多个使用逗号隔开)", required = true, dataType = "string", paramType = "query")
    })
    public AjaxResult isExistsReport(String indicatorsId, String userDivision) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        String[] indicatorsIds = iIdtIndicatorsService.listInIndicatorsIds(indicatorsId);
        String[] userDivisions = userDivision.split(",");
        Map<String, String> deptMap = iIdtIndicatorsService.getDeptNameMap();
        // 重复数据
        List<IdtReportValue> repeatingData = new ArrayList<>();
        for (int i = 0; i < indicatorsIds.length; i++) {
            IdtIndicators idtIndicators = iIdtIndicatorsService.getById(indicatorsIds[i]);
            //获取指标上报值列表数据
            List<IdtReportFill> idtReportFills = idtReportFillService.listByData(Arrays.asList(indicatorsIds[i]), userDivisions);
            for (IdtReportFill idtReportFill : idtReportFills) {
                if(StringUtils.isBlank(idtReportFill.getValue())){
                    continue;
                }
                IdtReportValue idtReportValue = new IdtReportValue();
                BeanUtils.copyProperties(idtReportFill, idtReportValue);
                idtReportValue.setIdtName(idtIndicators.getName());
                idtReportValue.setIdtCode(idtIndicators.getCode());
                idtReportValue.setValue(idtReportFill.getValue());
                LambdaQueryWrapper<IdtReportValue> queryWrapper = new QueryWrapper().lambda();
                queryWrapper.eq(IdtReportValue::getYear,idtReportValue.getYear());
                queryWrapper.eq(IdtReportValue::getDivisionCode,idtReportValue.getDivisionCode());
                queryWrapper.eq(IdtReportValue::getIndicatorsId,indicatorsIds[i]);
                List<IdtReportValue> sourceIdtReportValueList = iIdtReportValueService.list(queryWrapper);
                if (sourceIdtReportValueList.size() > 0) {
                    idtReportValue.setOldValue(sourceIdtReportValueList.get(0).getValue());
                    idtReportValue.setId(sourceIdtReportValueList.get(0).getId());
                    idtReportValue.setIdtDutyDepartment(iIdtIndicatorsService.getDeptNameStr(idtIndicators.getDutyDepartment(), deptMap));
                    idtReportValue.setIdtDutyCompany(iIdtIndicatorsService.getDeptNameStr(idtIndicators.getDutyCompany(), deptMap));
                    repeatingData.add(idtReportValue);
                }
            }
        }
        String resultCodes = "";
        for (IdtReportValue obj : repeatingData) {
            if (!resultCodes.contains(obj.getIdtName())) {
                resultCodes += StringUtils.isBlank(resultCodes) ? (obj.getIdtName()+ "("+obj.getIdtDutyCompany()+")" ):
                        "," + (obj.getIdtName()+ "("+obj.getIdtDutyCompany()+")" );
            }
        }
        resultMap.put("resultCodes",resultCodes);
        resultMap.put("repeatingData",repeatingData);
        return new AjaxResult(resultMap);
    }

    /**
    * @描述: 发布
    * @入参:
    * @出参:
    * @作者: 代鹏刚
    * @日期: 2020/11/7 15:19
    **/
    @PostMapping("/publishReport")
    @ApiOperation(value = "发布")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "indicatorsId", value = "指标ID（多个使用逗号隔开）", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "userDivision", value = "行政区划编码(多个使用逗号隔开)", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "repeatIds", value = "需更新数值（多个使用逗号隔开）", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "fillType", value = "填报类型", required = true, dataType = "string", paramType = "query")
    })
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult publishReport(String indicatorsId, String userDivision, String repeatIds) throws Exception {
        String[] userDivisions = userDivision.split(",");
        String[] indicatorsIds = iIdtIndicatorsService.listInIndicatorsIds(indicatorsId);
        // 存储新增、更新指标集合
        List<IdtReportValue> saveUpdateList = new ArrayList<>();
        // 存储发布后需删除的指标监测值
        List<String> delIds = new ArrayList<>();
        // 存储状态更新的指标
        List<IdtIndicators> updateList = new ArrayList<>();
        for (int i = 0; i < indicatorsIds.length; i++) {
            IdtIndicators idtIndicators = iIdtIndicatorsService.getById(indicatorsIds[i]);
            //获取指标上报值列表数据
            List<IdtReportFill> idtReportFills = idtReportFillService.listByData(Arrays.asList(indicatorsIds[i]), userDivisions);
            for (IdtReportFill idtReportFill : idtReportFills) {
                delIds.add(idtReportFill.getId());
                IdtReportValue idtReportValue = new IdtReportValue();
                BeanUtils.copyProperties(idtReportFill, idtReportValue);
                idtReportValue.setIdtCode(idtIndicators.getCode());
                idtReportValue.setId(UuidUtil.get32UUID());
                LambdaQueryWrapper<IdtReportValue> queryWrapper = new QueryWrapper().lambda();
                queryWrapper.eq(IdtReportValue::getYear,idtReportValue.getYear());
                queryWrapper.eq(IdtReportValue::getDivisionCode,idtReportValue.getDivisionCode());
                queryWrapper.eq(IdtReportValue::getIndicatorsId,indicatorsIds[i]);
                List<IdtReportValue> sourceIdtReportValueList = iIdtReportValueService.list(queryWrapper);
                if (sourceIdtReportValueList.size() > 0) {
                    if(repeatIds != null && repeatIds.contains(sourceIdtReportValueList.get(0).getId())){
                        IdtReportValue reportValue = sourceIdtReportValueList.get(0);
                        reportValue.setValue(idtReportValue.getValue());
                        reportValue.setExplain(idtReportValue.getExplain());
                        idtReportValue = reportValue;
                    }else {
                        continue;
                    }
                }
                idtReportValue.setCreator(this.getUser().getUserId().toString());
                idtReportValue.setCreateTime(new Date());
                idtReportValue.setOrgId(AuthUtil.getDeptId().toString());
                //判断是否统一
                Integer unify = iIdtReportValueService.isUnify(idtReportValue.getIndicatorsId(), idtReportValue.getYear() + "", idtReportValue.getDivisionCode(), idtReportValue.getValue());
                idtReportValue.setIsUnify(unify);
                //判断是否达标
                Integer standard = iIdtReportValueService.isStandard(idtReportValue.getIndicatorsId(), idtReportValue.getYear() + "", idtReportValue.getDivisionCode(), idtReportValue.getValue());
                idtReportValue.setIsStandard(standard);
                //将临时表附件关联到指标上报表
                iIdtReportFileService.updateByReportId(idtReportFill.getId(), idtReportValue.getId());
                saveUpdateList.add(idtReportValue);
            }
        }
        if (saveUpdateList.size() > 0) {
            // 批量保存更新
            iIdtReportValueService.saveOrUpdateBatch(saveUpdateList);
            // 更新指标表中的更新状态
            updateList = iIdtIndicatorsService.updateReportStatus(indicatorsId);
            // 清理临时表数据
            idtReportFillService.removeByIds(delIds);
        }
        return new AjaxResult(updateList);
    }

    private void prepareData(IdtReportFill idtReportFill, boolean isSave) {
        if(isSave){
            idtReportFill.setCreator(this.getUser().getUserId().toString());
            idtReportFill.setCreateTime(new Date());
            //防止误修改
            idtReportFill.setModifier(null);
            idtReportFill.setModifyTime(null);
        }else{
            idtReportFill.setModifier(this.getUser().getUserId().toString());
            idtReportFill.setModifyTime(new Date());
            //防止误修改
            idtReportFill.setCreator(null);
            idtReportFill.setCreateTime(null);
        }
    }

    /**
     * 检查数据是否合法
     * @param reportFills 要检查的数据
     * @return null -- 没问题，非null -- 错误信息
     * @author 陈宏成
     * @date 2021-12-28
     */
    private AjaxResult checkDataLegitimate(List<IdtReportFill> reportFills){
        for(IdtReportFill reportFill : reportFills) {
            if (StringUtils.isBlank(reportFill.getIndicatorsId())){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "指标ID不能为空");
            }
            if (Objects.isNull(reportFill.getYear())){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "上报年份不能为空");
            }
            if (StringUtils.isBlank(reportFill.getValue())){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "评估值不能为空");
            }
            if (StringUtils.isBlank(reportFill.getDivisionCode())){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, "行政区划不能为空");
            }
        }
        return null;
    }

    /**
     * 处理Excel导入的数据
     * @param excelList Excel表格读取出来的数据
     * @return null -- 没问题，非null -- 错误信息
     * @author 陈宏成
     * @date 2021-12-28
     */
    private AjaxResult prepareExcelData(List<List<String>> excelList){
        if (CollectionUtils.isEmpty(excelList) || excelList.size() <= 1){
            return new AjaxResult(StatusCode.ERROR_CODE_40005, "导入文件数据为空！");
        }
        // 去除数据的前后空格
        for(int j = 1; j < excelList.size(); j++) {
            List<String> rowList = excelList.get(j);
            // 对每个单元格进行去除空格
            for(int i = 0; i < rowList.size(); i++) {
                if(rowList.get(i) == null){
                    rowList.set(i,"");
                }else{
                    rowList.set(i,rowList.get(i).trim());
                }
            }
            // 去除指标编码的小数点
            int idtCodeIndex = 0;
            if(StringUtils.isBlank(rowList.get(idtCodeIndex))){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, String.format("第 %s 行指标编码为空，请补充完整。", j + 1));
            }else if (rowList.get(idtCodeIndex).contains(".")){
                rowList.set(idtCodeIndex, rowList.get(idtCodeIndex).substring(0, rowList.get(idtCodeIndex).indexOf(".") ));
            }
            // 去除行政区划编码的小数点
            int divisionCodeIndex = 4;
            if(StringUtils.isBlank(rowList.get(divisionCodeIndex))){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, String.format("第 %s 行行政区划编码为空，请补充完整。", j + 1));
            }else if (rowList.get(divisionCodeIndex).contains(".")){
                rowList.set(divisionCodeIndex, rowList.get(divisionCodeIndex).substring(0, rowList.get(divisionCodeIndex).indexOf(".") ));
            }
            // 去除年份的小数点
            int yearIndex = 5;
            if(StringUtils.isBlank(rowList.get(yearIndex))){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, String.format("第 %s 行上报年份为空，请补充完整。", j + 1));
            }else if (rowList.get(yearIndex).contains(".")){
                rowList.set(yearIndex, rowList.get(yearIndex).substring(0, rowList.get(yearIndex).indexOf(".") ));
            }
            // 检查评估值是否为空
            int valueIndex = 6;
            if(StringUtils.isBlank(rowList.get(valueIndex))){
                return new AjaxResult(StatusCode.ERROR_CODE_40005, String.format("第 %s 行上报值为空，请补充完整。", j + 1));
            }
        }
        return null;
    }
}
